import javax.jnlp.ClipboardService;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: mac
 * Date: 2022-09-14
 * Time: 17:23
 */
class MyArrayList<E>{
    private Object[] elementData;
    private int usedSize;//有效数据个数

    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

    public MyArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }

    public MyArrayList(int capacity) {
        //参数判断
        if (capacity > 0) {
            this.elementData = new Object[capacity];
        } else if (capacity == 0) {
            this.elementData = new Object[0];
        } else {
            throw new IllegalArgumentException("初始化容量不能为负");
        }
    }

    /**
     * 添加数据add
     * 尾插法
     * @param e 数据
     * @return boolean
     */
    public boolean add(E e) {
        ensureCapacityInternal(usedSize + 1);
        elementData[usedSize++] = e;
        return true;
    }

    private void ensureCapacityInternal(int minCapacity) {
        //1.计算出需要的容量
        int capacity = calculateCapacity(elementData, minCapacity);
        //2.拿着计算出的容量判断是否需要扩容
        ensureExplicitCapacity(capacity);
    }

    private static int calculateCapacity(Object[] elementData, int minCapacity) {
        //1.是否之前elementData数组分配过大小
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA){
            return Math.max(10,minCapacity);
        }
        return minCapacity;
    }

    private void ensureExplicitCapacity(int minCapacity) {
        //进不去if语句，数组还未满
        if (minCapacity - elementData.length > 0 ){
            grow(minCapacity);
        }
    }
    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
    private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;
        //1.5X
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
        // minCapacity is usually close to size, so this is a win:
        elementData = Arrays.copyOf(elementData, newCapacity);
    }
    private static int hugeCapacity(int minCapacity) {
        if (minCapacity < 0) // overflow
            throw new OutOfMemoryError();
        return (minCapacity > MAX_ARRAY_SIZE) ?
                Integer.MAX_VALUE :
                MAX_ARRAY_SIZE;
    }

    /**
     * 指定位置添加元素
     * @param index 添加位置
     * @param e 要添加的元素
     */
    public void add(int index, E e){
        //1.计算出需要的容量
        rangeCheckForAdd(index);

        //2.确定容量
        ensureCapacityInternal(usedSize + 1);  // Increments modCount!!
        System.arraycopy(elementData, index, elementData, index + 1,
                usedSize - index);
        elementData[index] = e;
        usedSize++;
    }

    private void rangeCheckForAdd(int index){
        if (index < 0 || index > size()){
            throw new IndexOutOfBoundsException("index 位置不合法，不能插入！");
        }
    }

    /**
     * 获取顺序表大小
     */
    public int size() {
        return this.usedSize;
    }


    @Override
    public String toString() {
        return "MyArrayList{" +
                "elementData=" + Arrays.toString(elementData) +
                ", usedSize=" + usedSize +
                '}';
    }
}
public class TestDemo {
    public static void main7(String[] args) {
        MyArrayList<String> list = new MyArrayList<>();
        list.add("ab");
        list.add("abc");
        list.add("abcd");
        list.add("abcde");
        System.out.println(list);
        list.add(4,"蔡徐坤");
        System.out.println(list);
    }
    public static void main6(String[] args) {
        //看源码 - 发现list1初始大小为0
        ArrayList<String> list1 = new ArrayList<>();
        //扩容机制，当第一次add数据时，顺序表被初始化为10个内存
        //当这10个空间放满了，开始扩容 1.5x - 看源码
        //如果调用的是给定容量的构造方法，那么大小即为你的容量，之后还是1.5x扩容
        list1.add("蔡徐坤");


        ArrayList<String> list2 = new ArrayList<>(13);
    }
    //基本方法
    public static void main5(String[] args) {
        //ArrayList.add默认尾插法
        ArrayList<String> list2 = new ArrayList<>();
        list2.add("a");
        list2.add("b");
        list2.add("c");
        list2.add("d");
        list2.add("f");
        System.out.println(list2);
        System.out.println("=========");

        /*System.out.println(list2);
        list2.add(0,"蔡徐坤");
        System.out.println(list2);

        System.out.println("=========");
        ArrayList<String> list3 = new ArrayList<>();
        list3.add("我是测试List1");
        list3.add("我是测试List2");
        list3.add("我是测试List3");
        list3.addAll(1,list2);
        System.out.println(list3);*/


        //list2.remove(0);
        /*boolean ret = list2.remove("a");
        System.out.println(ret);
        System.out.println(list2);*/

        /*String ret = list2.get(0);
        System.out.println(ret);*/

        /*String ret = list2.set(0,"蔡徐坤");//返回值为被替换元素
        System.out.println(ret);
        System.out.println(list2);*/

        /*list2.clear();
        System.out.println(list2);*/

        //System.out.println(list2.contains("蔡徐坤"));

        //System.out.println(list2.indexOf("a"));

        //System.out.println(list2.lastIndexOf("c"));

        //作业2：思考如何实现sub
        List<String> sub = list2.subList(1,3);
        System.out.println(sub);
        System.out.println(list2);
        System.out.println("+++++++++++");
        sub.set(0,"蔡徐坤");
        System.out.println(sub);
        System.out.println(list2);
    }
    //打印方法
    public static void main(String[] args) {
        //ArrayList - 线程不安全 CopyOnWriteArrayList - 线程安全
        //ArrayList<String> list2 = new ArrayList<>();
        CopyOnWriteArrayList list2 = new CopyOnWriteArrayList();
        list2.add("hello");
        list2.add("bit");
        list2.add("haha");

        System.out.println("==迭代器List用===");
        ListIterator<String> listIterator = list2.listIterator();
        while (listIterator.hasNext()){
            //用了CopyOnWriteArrayList抛异常
            String ret = listIterator.next();
            if (ret.equals("hello")) {
                //listIterator.add("ag");
                list2.add("ag");
            } else{
                System.out.print(ret + " ");
            }
        }
        System.out.println();
        System.out.println(list2);
    }
    public static void main4(String[] args) {
        ArrayList<String> list2 = new ArrayList<>();
        list2.add("hello");
        list2.add("bit");
        list2.add("haha");

        ListIterator<String> it = list2.listIterator();
        while (it.hasNext()){
            String ret = it.next();//必须先迭代next所有元素，才能用remove删除
            if (ret.equals("hello")) {
                list2.add("ag");
            }else {
                System.out.print(ret + " ");
            }
        }
        System.out.println();
        System.out.println(list2);
    }
    public static void main2(String[] args) {
        System.out.println("=====toString===");
        ArrayList<String> list2 = new ArrayList<>();
        list2.add("hello");
        list2.add("bit");
        list2.add("haha");
        System.out.println(list2);

        System.out.println("====for..each===");
        for (String str:list2
             ) {
            System.out.print(str + " ");
        }
        System.out.println();

        System.out.println("======for..=====");
        for (int i = 0; i < list2.size(); i++) {
            System.out.print(list2.get(i) + " ");
        }
        System.out.println();

        System.out.println("======迭代器=====");
        Iterator<String> it = list2.iterator();
        while (it.hasNext()){
            System.out.print(it.next() + " ");
        }
        System.out.println();

        System.out.println("==迭代器List用===");
        ListIterator<String> listIterator = list2.listIterator();
        while (listIterator.hasNext()){
            System.out.print(listIterator.next() + " ");
        }

    }

    public static void subListadd(String[] args) {
        //初始化
        List<String> list = new LinkedList<>();


        //添加元素
        list.add("hello");
        list.add("bit");
        list.add("bit");
        list.add("world");
        System.out.println(list);
        System.out.println("========");

        //截取部分list - 左闭右开区间
        List<String> list1 = list.subList(0,1);
        System.out.println(list1);
    }
    public static void contindexOf(String[] args) {
        //初始化
        List<String> list = new LinkedList<>();


        //添加元素
        list.add("hello");
        list.add("bit");
        list.add("bit");
        list.add("world");
        System.out.println(list);
        System.out.println("========");

        //判断字段是否在线性表中
        System.out.println(list.contains("bit"));
        System.out.println("========");

        //返回字段所在的下标
        System.out.println(list.indexOf("bit"));//从头找
        System.out.println(list.lastIndexOf("bit"));//从尾找

    }
    public static void setGet(String[] args) {
        //初始化
        ArrayList<String> list2 = new ArrayList<>();

        //添加元素
        list2.add("hello");
        list2.add("bit");
        list2.add("world");
        System.out.println(list2);
        System.out.println("========");

        //get 指定位置元素
        System.out.println(list2.get(0));
        System.out.println(list2.get(2));
        System.out.println("========");

        //set指定位置元素
        list2.set(0,"a");
        list2.set(2,"g");
        System.out.println(list2);
    }
    public static void removeclear(String[] args){
        //初始化
        ArrayList<String> list2 = new ArrayList<>();

        //添加元素
        list2.add("hello");
        list2.add("bit");
        list2.add("world");
        System.out.println(list2);
        System.out.println("========");

        //remove指定位置元素
        list2.remove(0);
        list2.remove(1);
        System.out.println(list2);
        System.out.println("========");

        //remove出现的第一个关键字
        list2.add("a");
        list2.add("bit");
        list2.remove("bit");
        System.out.println(list2);
        System.out.println("========");

        //clear 整个list
        list2.clear();
        System.out.println(list2);
    }
    public static void initAdd(String[] args) {
        //初始化
        List<String> list1 = new ArrayList<>(20);
        ArrayList<String> list2 = new ArrayList<>();

        //添加元素
        list2.add("hello");
        list2.add("bit");
        list2.add("world");
        System.out.println(list2);
        System.out.println("========");

        //指定位置添加元素
        list2.add(0,"a");
        list2.add(4,"g");
        System.out.println(list2);
        System.out.println("========");

        //使用另外一个ArrayList对list3进行初始化,类型必须相同
        ArrayList<String> list3 = new ArrayList<>(list2);
        System.out.println(list3);
        System.out.println("========");

        //list3中尾插list2中的所有元素
        list3.addAll(list2);
        System.out.println(list3);
    }
}
